package org.theqcp.wow.model.items;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

import org.theqcp.wow.model.mechanics.Attribute;
import org.theqcp.wow.model.mechanics.Slot;

public class Equipment {

	/**
	 * Table for storing stats
	 */
	private HashMap<Attribute, Double> statTable = new HashMap<Attribute, Double>();
	
	/**
	 * Item ID for looking up item (again! / cross service)
	 */
	private String itemId;
	
	/**
	 * The slot it can be equiped in
	 * 
	 */
	private Slot equipSlot;
	
	/**
	 * Item class number
	 */
	private String itemClassNumber;
	
	/**
	 * Item class name
	 */
	private String itemClassName;
	
	/**
	 * Item subclass number
	 */
	private String itemSubClassNumber;
	
	/**
	 * Item subclass name
	 */
	private String itemSubClassName;	
	
	/**
	 * Item name
	 */
	private String itemName;
	
	
	/**
	 * Get a full string representation of the item.
	 * 
	 */
	public String toString() {
		
		String output = "";
		
		output += String.format("ID: [%s]\n", this.itemId); 
		output += String.format("Category: [%s - %s]\n",this.itemClassNumber,this.itemClassName);
		output += String.format("Slot: [%s]\n", this.equipSlot != null ? this.equipSlot.toString() : "");
		output += String.format("Name: [%s]\nStats: [\n", this.itemName);
		
		//print stats
		for(Attribute stat : this.statTable.keySet()) {
			output += String.format("\t%s: %.2f\n", stat.getIdentifier(), this.statTable.get(stat).doubleValue());
		}
		
		output += "]";
		
		return output;
		
	}	

	/**
	 * Get the item id.
	 * 
	 * @return
	 */
	public String getItemId() {
		return itemId;
	}

	/**
	 * Set the item id
	 * 
	 * @param itemId
	 */
	public void setItemId(String itemId) {
		this.itemId = itemId;
	}

	/**
	 * Get the item name
	 * 
	 * @return
	 */
	public String getItemName() {
		return itemName;
	}

	/**
	 * Set the item name
	 * 
	 * @param itemName
	 */
	public void setItemName(String itemName) {
		this.itemName = itemName;
	}
	
	/**
	 * Get a stat from the stat table.  If a stat is not in the table,
	 * then a 0.0 will be returned.
	 * 
	 * @param stat the stat type to retrieve
	 * @return
	 */
	public Double getStat(Attribute stat) {
		
		Double statValue = new Double(0.0);
		
		if(this.statTable.containsKey(stat)) {
			statValue = this.statTable.get(stat);
		}
	
		return statValue;
	}

	/**
	 * Sets a stat in the stat table.  Null stats are rejected.  0 stats are
	 * not saved to preserve memory in the table.  (Mainly concerned with 
	 * serialization and suchlike)
	 * <br/><br/>
	 * Postconditions:<ul>
	 * <li>A non-null, non-zero stat is added into the stat table with a key of stat</li></ul> 
	 * 
	 * @param stat the stat type to add
	 * @param statValue the value of the stat
	 */
	public void setStat(Attribute stat, Double statValue) {
		
		if(statValue == null || statValue.equals(0.0)) return;
		
		if(this.statTable.containsKey(stat)) {
			this.statTable.remove(stat);
		}
		
		//put in table
		this.statTable.put(stat,statValue);
	}
	
	/**
	 * Get the number of stats <i>actually</i> set with non-null and non-zero values.
	 * 
	 * @return
	 */
	public int getAvailableStatCount() {
		return this.statTable.size();
	}	
	
	/**
	 * Get a list of available stats that have been set (with non-null, non-zero values) on the item.
	 * 
	 * @return
	 */
	public Set<Attribute> getAvailableStats() {
		return new HashSet<Attribute>(this.statTable.keySet());
	}
	
	/**
	 * Returns a copy of the stat table so that it can be accessed in the
	 * raw for whatever reason.
	 * 
	 * @return
	 */
	public HashMap<Attribute,Double> getRawTable() {
		
		//create new map
		HashMap<Attribute,Double> map = new HashMap<Attribute, Double>();
		
		//copy local map into this map
		map.putAll(this.statTable);
		
		//return map
		return map;
	}
	
	/**
	 * Get ItemClass number
	 * 
	 * @return
	 */
	public String getItemClassNumber() {
		return itemClassNumber;
	}

	/**
	 * Set ItemClass number
	 * 
	 * @param categoryNumber
	 */
	public void setItemClassNumber(String itemClassNumber) {
		this.itemClassNumber = itemClassNumber;
	}

	/**
	 * Get ItemClass name.
	 * 
	 * @return
	 */
	public String getItemClassName() {
		return itemClassName;
	}

	/**
	 * Get ItemClass name.
	 * 
	 * @param itemClassName
	 */
	public void setItemClassName(String itemClassName) {
		this.itemClassName = itemClassName;
	}

	/**
	 * Get ItemSubClass number.
	 * 
	 * @return
	 */
	public String getItemSubClassNumber() {
		return itemSubClassNumber;
	}

	/**
	 * Set ItemSubClass number.
	 * 
	 * @param itemSubClassNumber
	 */
	public void setItemSubClassNumber(String itemSubClassNumber) {
		this.itemSubClassNumber = itemSubClassNumber;
	}

	
	/**
	 * Get ItemSubClass name.
	 * 
	 * @return
	 */
	public String getItemSubClassName() {
		return itemSubClassName;
	}

	/**
	 * Set ItemSubClass name.
	 * 
	 * @param itemSubClassName
	 */
	public void setItemSubClassName(String itemSubClassName) {
		this.itemSubClassName = itemSubClassName;
	}

	/**
	 * The slot that the item can be equiped in.
	 * 
	 * @return
	 */
	public Slot getEquipSlot() {
		return equipSlot;
	}

	/**
	 * Set the slot that the item can be equiped in.
	 * 
	 * @param equipSlot
	 */
	public void setEquipSlot(Slot equipSlot) {
		this.equipSlot = equipSlot;
	}

	
}
